<?php
class Soul_Request_Http_Handler{
    
    protected function findController(){
        $router = Soul_Request_Factory::getRouter();
        $className = 'component_'.$router->getComponent()
                   .'_controller_'.$router->getDomain()->getName()
                   .'_'.str_replace('-', '_', $router->getController());
        $result = Soul_Loader::loadClass($className);
        if(empty($result)){
            throw new Exception('Not found controller ['.$result.']');
        }        
        return $result;
    }

	protected function findAction($controller){
        $router = Soul_Request_Factory::getRouter();
        $action = Soul_Util_String::lowerFirstChar(Soul_Util_String::underlineToWord(str_replace('-', '_', $router->getAction())));
        $methods = array();
        if($GLOBALS[RC]->getRequest()->isAjax()){
            $methods[] = $action.'Ajax';
        }            
        $methods[] = $action.ucfirst($GLOBALS[RC]->getRequest()->getMethod());         
        $methods[] = $action;
        if(method_exists($controller, 'mappingAction')){
            $mapping = $controller->mappingAction();
            foreach($methods as $method){
                if(isset($mapping[$method])){
                    return $mapping[$method].'Action';
                }
            }            
        }
        
        foreach($methods as $method){
            if(method_exists($controller, $method.'Action')){
                return $method.'Action';
            }
        }

		throw new Exception('Not found action ['.$action.'] in controller ['.get_class($controller).']');
	}
    
    protected function getActionArgument(ReflectionMethod $method){
		$methodParams = array();
		$req = $GLOBALS[RC]->getRequest();
		if($method->getNumberOfParameters() > 0){
			foreach($method->getParameters() as $parameter){
				$has = $req->hasParameter($parameter->getName());
				$iso = $parameter->isOptional();
				if ($has) {
					$rv = $req->getParameter($parameter->getName());
					$pc = $parameter->getClass();
					if(!is_null($pc) && is_array($rv)){
						if($pc->isSubclassOf('Soul_Object')){
							$rv = $pc->newInstance()->addData($rv);
						}elseif($pc->getName() == 'Soul_Validation_Validator'){
							$rv = $pc->newInstance()->setData($rv);
						}
					}
				}else if($iso){
					$rv = $parameter->getDefaultValue();
				}else{
					throw new Exception('invalid request parameter ['.$parameter->getName().']');
				}
				$methodParams[] = $rv;
			}
		}
        return $methodParams;       
    }
    
//    protected function filterHandler(ReflectionFunction $function){
//        if(preg_match_all('/@handlerAttribute/ig', $function->getDocComment(), $matches)){
//            
//        }
//    }

	public function handle(){
        $controllerClass = $this->findController();
        $controller = new $controllerClass();
//        Soul_Annotation_Executor::executeFromClass(new ReflectionClass($controllerClass));
        $action = $this->findAction($controller);
        $args = $this->getActionArgument(new ReflectionMethod($controller, $action));
        $result = call_user_func_array(array($controller, $action), $args);
		$result->execute();
	}
}